package channelService

import (
	"errors"
	"gitee.com/fierce_wolf/go-fox-edge-common/commComp/serialPort"
	"gitee.com/fierce_wolf/go-fox-edge-common/commRedisRpc"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Map"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Number"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/OS"
	"github.com/jacobsa/go-serial/serial"
	"go-fox-edge-channel-serial/channelEntity"
)

type channelService struct {
}

func (e *channelService) OpenChannel(channelName string, channelParam map[string]interface{}) error {
	// 创建一个实体对象
	serialChannelEntity := channelEntity.Map.Get(channelName)
	if serialChannelEntity == nil {
		serialChannelEntity = &channelEntity.SerialChannelEntity{}
		serialChannelEntity.ChannelName = channelName
		serialChannelEntity.SerialPort = &serialPort.SerialPort{}
		channelEntity.Map.Set(channelName, serialChannelEntity)
	}

	// 取出配置参数
	serialName := Map.GetOrDefault(channelParam, "serialName", "").(string)
	baudRate := Number.MakeInt(Map.GetOrDefault(channelParam, "baudRate", 9600))
	dataBits := Number.MakeInt(Map.GetOrDefault(channelParam, "databits", 8))
	stopBits := Number.MakeInt(Map.GetOrDefault(channelParam, "stopbits", 1))
	parity := Map.GetOrDefault(channelParam, "parity", "N").(string)
	packInterval := Number.MakeInt(Map.GetOrDefault(channelParam, "packInterval", 0))
	fullDuplex := true == Map.GetOrDefault(channelParam, "fullDuplex", false)

	if OS.Type.IsLinux() {
		serialName = "/dev/" + serialName
	}

	// 生成配置实体
	configEntity := &channelEntity.SerialConfigEntity{}
	configEntity.SerialName = serialName
	configEntity.BaudRate = baudRate
	configEntity.DataBits = dataBits
	configEntity.StopBits = stopBits
	configEntity.MinPackInterval = packInterval
	configEntity.FullDuplex = fullDuplex
	if parity == "N" {
		configEntity.Parity = serial.PARITY_NONE
	}
	if parity == "O" {
		configEntity.Parity = serial.PARITY_ODD
	}
	if parity == "E" {
		configEntity.Parity = serial.PARITY_EVEN
	}

	// 保存配置
	serialChannelEntity.Config = configEntity

	// 打开串口
	return e.openSerial(channelName)
}

func (e *channelService) openSerial(channelName string) error {
	serialChannelEntity := channelEntity.Map.Get(channelName)
	if serialChannelEntity == nil {
		return errors.New("该channel实体对象不存在:" + channelName)
	}

	if serialChannelEntity.Config == nil {
		return errors.New("配置参数不正确:" + channelName)
	}

	// 打开串口
	if !serialChannelEntity.SerialPort.IsOpen() {
		// 配置串口
		options := serial.OpenOptions{
			PortName:        serialChannelEntity.Config.SerialName,     // 串口名称
			BaudRate:        uint(serialChannelEntity.Config.BaudRate), // 波特率
			DataBits:        uint(serialChannelEntity.Config.DataBits), // 数据位
			StopBits:        uint(serialChannelEntity.Config.StopBits), // 停止位
			ParityMode:      serialChannelEntity.Config.Parity,         //波特率
			MinimumReadSize: 4,                                         // 最小读取字节数
		}

		// 打开串口
		err := serialChannelEntity.SerialPort.Open(options)
		if err != nil {
			return err
		}
	}

	return nil
}

func (e *channelService) CloseChannel(channelName string, channelParam map[string]interface{}) error {
	serialChannelEntity := channelEntity.Map.Get(channelName)
	if serialChannelEntity == nil {
		return nil
	}

	// 关闭串口
	serialChannelEntity.SerialPort.Close()

	// 删除实体
	channelEntity.Map.Remove(channelName)

	return nil
}

func (e *channelService) ManageChannel(requestVO *commRedisRpc.ChannelRequestVO) (*commRedisRpc.ChannelRespondVO, error) {
	return commRedisRpc.Type.ChannelRespondVO.Error(requestVO, "不支持管理"), nil
}

func (e *channelService) Execute(requestVO *commRedisRpc.ChannelRequestVO) (*commRedisRpc.ChannelRespondVO, error) {
	serialChannelEntity := channelEntity.Map.Get(requestVO.Name)
	if serialChannelEntity == nil {
		return nil, errors.New("该channel不存在:" + requestVO.Name)
	}

	if serialChannelEntity.Config == nil {
		return nil, errors.New("该channel上的配置参数不正确:" + requestVO.Name)
	}

	if serialChannelEntity.SerialPort == nil {
		return nil, errors.New("串口无法打开:" + requestVO.Name)
	}

	if serialChannelEntity.Config.FullDuplex {
		return nil, errors.New("异步全双工模式，不允许进行半双工操作:" + requestVO.Name)
	}

	return execute.execute(serialChannelEntity, requestVO)
}

func (e *channelService) Publish(requestVO *commRedisRpc.ChannelRequestVO) error {
	serialChannelEntity := channelEntity.Map.Get(requestVO.Name)
	if serialChannelEntity == nil {
		return errors.New("该channel不存在:" + requestVO.Name)
	}

	if serialChannelEntity.Config == nil {
		return errors.New("该channel上的配置参数不正确:" + requestVO.Name)
	}

	if serialChannelEntity.SerialPort == nil {
		return errors.New("串口无法打开:" + requestVO.Name)
	}

	return publish.publish(serialChannelEntity, requestVO)
}

func (e *channelService) Report() ([]*commRedisRpc.ChannelRespondVO, error) {
	return nil, errors.New("不支持Report操作")
}
